package br.com.massai.model.entity;

import java.io.Serializable;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

import br.com.massai.view.enums.RoleEnum;
import br.com.massai.view.enums.StatusEnum;
import br.com.massai.view.utils.StringUtil;

@Entity
@Table(name = "USUARIO", schema = "PORTAL")
@SequenceGenerator(name = "seqUsuario", sequenceName = "seq_usuario", allocationSize = 1)
@NamedQueries({
	@NamedQuery(name = "Usuario.findAll", query = "SELECT u FROM Usuario u"),
	@NamedQuery(name = "Usuario.findLogin", query = "SELECT u FROM Usuario u WHERE LOWER(u.login) = LOWER(:login) AND u.senha = :senha AND u.ativo = :status"),
	@NamedQuery(name = "Usuario.duplicata", query = "SELECT COUNT(u) FROM Usuario u WHERE LOWER(u.login) = LOWER(:login) AND u.id <> :id"), 
	@NamedQuery(name = "Usuario.ativo", query = "SELECT u FROM Usuario u WHERE u.ativo =:ativo")
})
public class Usuario implements Serializable {

	private static final long serialVersionUID = 18577365964755933L;
	private static final String SENHA_PADRAO = "massai";

	@Id
	@Column(name = "ID_USUARIO")
	@GeneratedValue(generator = "seqUsuario", strategy = GenerationType.SEQUENCE)
	private Long id;

	@Column(name = "LOGIN", length = 20, nullable = false, unique = true, columnDefinition = "VARCHAR(20)")
	private String login;

	@Column(name = "SENHA", nullable = false, columnDefinition = "VARCHAR2(1000)")
	private String senha;

	@Column(name = "NOME", nullable = false, columnDefinition = "VARCHAR(100)")
	private String nome;

	@Column(name = "EMAIL", nullable = true, columnDefinition = "VARCHAR(255)")
	private String email;

	@Enumerated(EnumType.STRING)
	@Column(name = "ATIVO", nullable = false, columnDefinition = "CHAR CHECK(ATIVO IN ('A', 'I'))")
	private StatusEnum ativo;

	@Enumerated(EnumType.STRING)
	@Column(name = "ROLE", columnDefinition = "CHAR")
	private RoleEnum role;

	@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
	@Fetch(FetchMode.SUBSELECT)
	@JoinTable(name = "USUARIO_PRIVILEGIO", 
		joinColumns = @JoinColumn(name = "ID_USUARIO", referencedColumnName = "ID_USUARIO"), 
		inverseJoinColumns = @JoinColumn(name = "ID_PRIVILEGIO", referencedColumnName = "ID_PRIVILEGIO"))
	private List<Privilegio> privilegios;

	@Transient
	private ControleAcesso controleAcesso;

	public Usuario() {
		this.setSenha(SENHA_PADRAO);
	}
	
	public Usuario(StatusEnum s) {
		this();
		this.ativo = s;
	}

	public Usuario(RoleEnum role){
		this();
		this.ativo = StatusEnum.A;
		this.role = role;
	}
	
	public Usuario(String senha){
		this();
		this.setSenha(senha);
	}
	
	public void resetSenha(){
		this.setSenha(SENHA_PADRAO);
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj == null) return false;
		if(obj instanceof Usuario)
			if(((Usuario)obj).getId().equals(this.getId())) return true;
		return false;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getLogin() {
		return login;
	}

	public void setLogin(String login) {
		this.login = login;
	}

	public String getSenha() {
		return senha;
	}

	public void setSenha(String senha) {
		if(senha != null && !senha.trim().isEmpty())
			this.senha = StringUtil.encodedSHA256(senha);
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public List<Privilegio> getPrivilegios() {
		return privilegios;
	}

	public void setPrivilegios(List<Privilegio> privilegios) {
		this.privilegios = privilegios;
	}

	public StatusEnum getAtivo() {
		return ativo;
	}

	public void setAtivo(StatusEnum ativo) {
		this.ativo = ativo;
	}

	public RoleEnum getRole() {
		return role;
	}

	public void setRole(RoleEnum role) {
		this.role = role;
	}

	public ControleAcesso getControleAcesso() {
		return controleAcesso;
	}

	public void setControleAcesso(ControleAcesso controleAcesso) {
		this.controleAcesso = controleAcesso;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}
}
